package com.zkthink.ceres.app.authority.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.binarywang.wx.miniapp.util.QrcodeRequestExecutor;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zkthink.base.R;
import com.zkthink.cache.repository.CacheRepository;
import com.zkthink.cache.repository.RedisRepositoryImpl;
import com.zkthink.ceres.app.authority.dto.*;
import com.zkthink.ceres.app.authority.service.AuthService;
import com.zkthink.ceres.applet.commission.domain.entry.AppletCommission;
import com.zkthink.ceres.applet.commission.mapper.AppletCommissionMapper;
import com.zkthink.ceres.applet.referralrewards.domain.entry.Referralrewards;
import com.zkthink.ceres.applet.referralrewards.mapper.ReferralrewardsMapper;
import com.zkthink.ceres.common.constant.CacheKey;
import com.zkthink.ceres.common.constant.MemberConstants;
import com.zkthink.ceres.common.enums.MainRelativeEnum;
import com.zkthink.ceres.common.enums.ParameterUniqueEnum;
import com.zkthink.ceres.common.enums.RedSourceTypeEnum;
import com.zkthink.ceres.common.enums.WxAPIHttpUrl;
import com.zkthink.ceres.common.utils.*;
import com.zkthink.ceres.file.properties.FileServerProperties;
import com.zkthink.ceres.member.dto.RelationAccountSearchDTO;
import com.zkthink.ceres.member.entity.CeresMemberReferHis;
import com.zkthink.ceres.member.entity.Member;
import com.zkthink.ceres.member.entity.MemberPasswordHis;
import com.zkthink.ceres.member.event.LoginEvent;
import com.zkthink.ceres.member.service.CeresMemberReferHisService;
import com.zkthink.ceres.member.service.CeresRelationAcoountService;
import com.zkthink.ceres.member.service.MemberPasswordHisService;
import com.zkthink.ceres.member.service.MemberService;
import com.zkthink.ceres.member.vo.JumpWxaVo;
import com.zkthink.ceres.member.vo.MemberVO;
import com.zkthink.ceres.msgs.service.MobilePushService;
import com.zkthink.ceres.order.util.HttpUtils;
import com.zkthink.ceres.order.util.pojo.HttpResult;
import com.zkthink.ceres.pay.config.WxAppConfiguration;
import com.zkthink.ceres.sms.enumeration.TemplateCodeType;
import com.zkthink.context.BaseContextHandler;
import com.zkthink.database.mybatis.conditions.query.QueryWrap;
import com.zkthink.dozer.DozerUtils;
import com.zkthink.exception.code.ExceptionCode;
import com.zkthink.jwt.TokenUtil;
import com.zkthink.jwt.model.AuthInfo;
import com.zkthink.jwt.model.JwtUserInfo;
import com.zkthink.utils.StrPool;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.WxType;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import net.oschina.j2cache.CacheChannel;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import springfox.documentation.spring.web.json.Json;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.zkthink.ceres.applet.authority.config.AuthorityWebConfiguration.getMid;
import static com.zkthink.context.BaseContextHandler.getUserId;
import static com.zkthink.utils.DateUtils.DEFAULT_MONTH_FORMAT_SLASH;

/**
 * Created by kellen on 2020/5/3.
 */
@Service
@AllArgsConstructor
@Slf4j
public class AuthServiceImpl implements AuthService {


    @Autowired
    private MemberPasswordHisService memberPasswordHisService;

    private WxMaService wxMaService;

    @Resource
    private FileServerProperties fileProperties;

    @Resource
    private ReferralrewardsMapper referralrewardsMapper;


    @Autowired
    private CacheChannel channel;


    private MemberService memberService;

    private TokenUtil tokenUtil;

    private RedisRepositoryImpl redisRepository;

    private DozerUtils dozerUtils;

    private ApplicationEventPublisher publisher;

    public static final String WX_LOGIN_SESSION_KEY = "WX:SESSION:KEY:";

    private final PasswordEncoder passwordEncoder;

    private WxAppConfiguration wxAppConfiguration;

    @Autowired
    private CacheRepository cacheRepository;

    @Autowired
    private CeresRelationAcoountService ceresRelationAcoountService;

    @Resource
    private AppletCommissionMapper commissionMapper;


    @Override
    public R loginByWx(MiniAppLoginDTO miniAppLoginDTO) {
//        log.info("微信小程序登录返回:{}", JSON.toJSONString(miniAppLoginDTO));
        log.info("微信小程序登录返回:{}", JSON.toJSONString(miniAppLoginDTO));
        WxMaJscode2SessionResult result = loginByCode(miniAppLoginDTO.getCode());
        if (null == result) {
            return R.fail("微信登录失败");
        }
        String sessionKey = result.getSessionKey();
        log.info("登录获取sessionKey:{}", sessionKey);
        String openid = result.getOpenid();
        System.out.println(result.toString());
        Member member = memberService.findByOpenid(openid);
        System.out.println("-----------------" + member);
        Boolean a1 = false;
        if (null == member) {
//            member = Member.builder()
//                    .openid(openid)
//                    .loginTime(LocalDateTime.now())
//                    .unionid(result.getUnionid())
//                    .latitude(miniAppLoginDTO.getLatitude())
//                    .longitude(miniAppLoginDTO.getLongitude()).build();
            member = new Member();
            member.setOpenid(openid);
            member.setBalance(new BigDecimal(0));
            member.setCoupons(new BigDecimal(0));
            member.setIntegral(new BigDecimal(0));
            member.setTichneg(new BigDecimal(0));
            member.setPhone(miniAppLoginDTO.getPhone());
            member.setReferPhone(miniAppLoginDTO.getReferPhone());
            member.setNickname("微信用户");
            member.setHeadimg("https://xsy-1308896693.cos.ap-shanghai.myqcloud.com/admin/2022/02/a0272351-b471-4d2b-ac6d-0120926fb269.png");
            member.setLoginTime(LocalDateTime.now());
            //推荐注册奖励
            //获取推荐人信息
            String referPhone = miniAppLoginDTO.getReferPhone();
            if (StringUtils.isNotBlank(referPhone)) {
                Member referrer = memberService.findByphone(referPhone);
                if (null != referrer) {
                    Referralrewards referralrewards = referralrewardsMapper.selectById("1");
                    //直接推荐
                    if (referralrewards != null) {
                        referrer.setBalance(referrer.getBalance().add(referralrewards.getDirectreward()));
                        memberService.updateById(referrer);
                        //简介推荐
                        if (StringUtils.isNotBlank(referrer.getReferPhone())) {
                            Member byphone = memberService.findByphone(referrer.getReferPhone());
                            if (byphone != null) {
                                byphone.setBalance(byphone.getBalance().add(referralrewards.getIndirectreward()));
                                memberService.updateById(byphone);

                            }
                        }
                    }
                }
            }


        } else {
            member.setLoginNum(member.getLoginNum() + 1).setLoginTime(LocalDateTime.now());
        }
        memberService.saveOrUpdate(member);


//        if (member.getNickname() != null && member.getHeadimg() != null && member.getRongCloudToken() == null) {
//            if (!member.getNickname().isEmpty() && !member.getHeadimg().isEmpty()) {
//                System.out.println("第一次登陆");
//                String RongCloudToken = RongCloudUtils.getToken(member.getId(), member.getNickname(), member.getHeadimg());
//                member.setRongCloudToken(RongCloudToken);
//                memberService.updateById(member);
//            }
//        }
        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getOpenid(),
                member.getNickname() == null ? null : member.getNickname());
//        userInfo.setHeadimg(member.getHeadimg());
        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
        authInfo.setSessionKey(result.getSessionKey());
        authInfo.setOpenId(result.getOpenid());
        //缓存sessionKey
        redisRepository
                .setExpire(WX_LOGIN_SESSION_KEY + member.getId(), result.getSessionKey(), 3600 * 7);
        /**
         * 判断有没有推荐人,有推荐人的话，保存推荐历史
         * 得到分享者的电话
         * 20211115
         * 推薦人得到小红心
         * 1、看是否开启这个功能
         */
        //发布登录事件
        //成功登录事件
        publisher.publishEvent(
                LoginEvent.builder().mid(member.getId())
                        .salesId(miniAppLoginDTO.getSalesId())
                        .tenantCode(miniAppLoginDTO.getTenantCode()).build());
        return R.success(authInfo);
    }

    @Override
    public R loginByWxMa(HttpServletRequest request, MiniAppLoginDTO miniAppLoginDTO) {
        log.info("微信小程序登录返回:{}", JSON.toJSONString(miniAppLoginDTO));
        WxMaJscode2SessionResult result = loginByCode(miniAppLoginDTO.getCode());
        if (null == result) {
            return R.fail("微信登录失败");
        }
        String sessionKey = result.getSessionKey();
        log.info("登录获取sessionKey:{}", sessionKey);
        String openid = result.getOpenid();
        System.out.println(result.toString());
        Member member = memberService.findByOpenid(openid);
        System.out.println("-----------------" + member);
        Boolean a1 = false;
        if (null == member) {
//            member = Member.builder()
//                    .openid(openid)
//                    .loginTime(LocalDateTime.now())
//                    .unionid(result.getUnionid())
//                    .latitude(miniAppLoginDTO.getLatitude())
//                    .longitude(miniAppLoginDTO.getLongitude()).build();
            member = new Member();
            member.setOpenid(openid);
            member.setBalance(new BigDecimal(0));
            member.setCoupons(new BigDecimal(0));
            member.setTichneg(new BigDecimal(0));
            member.setIntegral(new BigDecimal(0));
            member.setReferPhone(miniAppLoginDTO.getReferPhone());
            member.setNickname("微信用户");
            member.setHeadimg("https://xsy-1308896693.cos.ap-shanghai.myqcloud.com/admin/2022/02/a0272351-b471-4d2b-ac6d-0120926fb269.png");
            member.setLoginTime(LocalDateTime.now());
            String env = request.getHeader("env");
            if (!env.equals("app")){
                member.setRoleType(3);
            }
            memberService.saveOrUpdate(member);
            //推荐注册奖励
            //获取推荐人信息
            String referPhone = miniAppLoginDTO.getReferPhone();
            if (StringUtils.isNotBlank(referPhone)) {
                Member referrer = memberService.findByphone(referPhone);
                if (null != referrer) {
                    Referralrewards referralrewards = referralrewardsMapper.selectById("1");
                    AppletCommission appletCommission = new AppletCommission();
                    appletCommission.setMid(member.getId());//当前订单的消费者
                    appletCommission.setPaySum(new BigDecimal(0));//订单的支付金额
                    appletCommission.setDirectCommissionRatio(referralrewards.getDirectrewardrate());//直接推荐比率
                    appletCommission.setDirectCommission(referralrewards.getDirectreward());//直接推荐提成金额
                    appletCommission.setIndirectCommissionRatio(referralrewards.getIndirectrewardrate());//间接推荐比率
                    appletCommission.setIndirectCommission(referralrewards.getDirectreward());//间接推荐提成
                    appletCommission.setCreateUser(String.valueOf(getUserId()));
                    appletCommission.setCreateTime(new Date());
                    //直接推荐
                    if (referralrewards != null) {
                        appletCommission.setDirectMid(String.valueOf(referrer.getId()));
                        referrer.setBalance(referrer.getBalance().add(referralrewards.getDirectreward()));
                        memberService.updateById(referrer);
                        //简介推荐
                        if (StringUtils.isNotBlank(referrer.getReferPhone())) {
                            Member byphone = memberService.findByphone(referrer.getReferPhone());
                            if (byphone != null) {
                                appletCommission.setIndirectMid(String.valueOf(byphone.getId()));
                                byphone.setBalance(byphone.getBalance().add(referralrewards.getIndirectreward()));
                                memberService.updateById(byphone);
                            }
                        }
                    }
                    commissionMapper.insert(appletCommission);
                }
            }
        } else {
            member.setLoginNum(member.getLoginNum() + 1).setLoginTime(LocalDateTime.now());
        }
        memberService.saveOrUpdate(member);


//        if (member.getNickname() != null && member.getHeadimg() != null && member.getRongCloudToken() == null) {
//            if (!member.getNickname().isEmpty() && !member.getHeadimg().isEmpty()) {
//                System.out.println("第一次登陆");
//                String RongCloudToken = RongCloudUtils.getToken(member.getId(), member.getNickname(), member.getHeadimg());
//                member.setRongCloudToken(RongCloudToken);
//                memberService.updateById(member);
//            }
//        }
        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getOpenid(),
                member.getNickname() == null ? null : member.getNickname());
//        userInfo.setHeadimg(member.getHeadimg());
        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
        authInfo.setSessionKey(result.getSessionKey());
        authInfo.setOpenId(result.getOpenid());
        authInfo.setMobile(member.getPhone());
        //缓存sessionKey
        redisRepository
                .setExpire(WX_LOGIN_SESSION_KEY + member.getId(), result.getSessionKey(), 3600 * 7);


        /**
         * 判断有没有推荐人,有推荐人的话，保存推荐历史
         * 得到分享者的电话
         * 20211115
         * 推薦人得到小红心
         * 1、看是否开启这个功能
         */
        //发布登录事件
        //成功登录事件
        publisher.publishEvent(
                LoginEvent.builder().mid(member.getId())
                        .salesId(miniAppLoginDTO.getSalesId())
                        .tenantCode(miniAppLoginDTO.getTenantCode()).build());
        return R.success(authInfo);
    }

    @Override
    public R generateScheme(JumpWxaVo jumpWxaVo) {
        JSONObject json = new JSONObject();
        String urlTwo = "";
        try {
            String accessToken = wxMaService.getAccessToken();
            String url = "https://api.weixin.qq.com/wxa/generatescheme";
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("is_expire", true);
            jsonObject.put("expire_type", 1);
            jsonObject.put("expire_interval", 1);
            JSONObject jumpWxaVObject = new JSONObject();
            jumpWxaVObject.put("path", jumpWxaVo.getPath());
            jumpWxaVObject.put("query", jumpWxaVo.getQuery());
            jumpWxaVObject.put("env_version", "trial");
            jsonObject.put("jump_wxa", jumpWxaVObject);
            String post = wxMaService.post(url, jsonObject);
            json = JSON.parseObject(post);
            if (!json.containsKey("openlink")) {
                return R.fail(json.getString("errmsg"));
            }
            String openlink = json.getString("openlink");
            String path = "https://sanshitang1863.com/openLink.html?openlink=" + openlink;
            String fileName = UUID.randomUUID().toString() + StrPool.DOT + "png";
            //日期文件夹
            String relativePath = Paths.get(LocalDate.now().format(DateTimeFormatter.ofPattern(DEFAULT_MONTH_FORMAT_SLASH))).toString();
            // web服务器存放的绝对路径
//            String absolutePath = Paths.get(fileProperties.getStoragePath(), relativePath).toString();
            String absolutePath = "/opt/llc/file/";
            QcodeUtil.getQRCode(path, Paths.get(absolutePath, fileName).toString());
            urlTwo = "https://sanshitang1863.com/file/" + fileName;
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("openlink", json.getString("openlink"));
        jsonObject.put("Url", urlTwo);
        return R.success(jsonObject);
    }


    private WxMaJscode2SessionResult loginByCode(String code) {
        WxMaJscode2SessionResult result = null;
        try {
            result = wxMaService.jsCode2SessionInfo(code);
            log.info("微信登录获取session返回:{}", result);
        } catch (WxErrorException e) {
            log.error("微信小程序登录异常", e);
            return null;
        }
        return result;

    }


    @Override
    public R loginTest(String openid) {
        Member member = memberService.findByOpenid(openid);
        if (null == member) {
            member = Member.builder()
                    .openid(openid)
                    .nickname("test")
                    .loginTime(LocalDateTime.now())
                    .sex("1").build();
        } else {
            member.setLoginNum(member.getLoginNum() + 1).setLoginTime(LocalDateTime.now());
        }
        memberService.saveOrUpdate(member);
        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getOpenid(),
                member.getNickname());
        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
        return R.success(authInfo);
    }

    @Override
    public R bindPhone(Long mid, MiniAppAuthDTO authDTO) {
        mid = getMid();
        Member byphone = memberService.findByphone(authDTO.getPhone());
        if (byphone != null) {
            if (!byphone.getId().equals(mid)) {
                return R.fail("该手机号已绑定");
            }
        }
        Member member = Member.builder().phone(authDTO.getPhone()).account(authDTO.getPhone()).id(mid)
                .build();
        memberService.updateById(member);
        return R.success();
    }


    @Override
    public R bindWxUserInfo(MiniAppAuthDTO miniAppAuthDTO) {
        Long mid = BaseContextHandler.getUserId();
        Member member = memberService.findById(mid);
//        XsyMemberBase memberBase = xsyMemberBaseService.getOne()
        //获取用户信息
        String sessionKey = redisRepository.get(WX_LOGIN_SESSION_KEY + mid);
        if (StrUtil.isBlank(sessionKey)) {
            return R.fail(ExceptionCode.JWT_TOKEN_EXPIRED);
        }
        WxMaUserInfo wxMaUserInfo = wxMaService.getUserService()
                .getUserInfo(sessionKey, miniAppAuthDTO.getEncryptedData(), miniAppAuthDTO.getIv());
        WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(sessionKey, miniAppAuthDTO.getEncryptedData(), miniAppAuthDTO.getIv());


        if (wxMaUserInfo.getGender() != null && member.getSex() == null) {
            member.setSex(wxMaUserInfo.getGender());
        }
        if (wxMaUserInfo.getNickName() != null && (member.getNickname() == null || member.getNickname().isEmpty())) {
            member.setNickname(wxMaUserInfo.getNickName());
        }
        if (phoneNoInfo.getPhoneNumber() != null && (member.getPhone() == null || member.getPhone().isEmpty())) {
            member.setPhone(phoneNoInfo.getPhoneNumber());
        }

        MemberVO memberVO = new MemberVO();
        if (phoneNoInfo.getPhoneNumber() != null && !phoneNoInfo.getPhoneNumber().isEmpty()) {
            /**
             * 判断电话是否已经注册，已经注册则合并
             */
            Member byAccount = memberService.findByAccount(phoneNoInfo.getPhoneNumber());
            if (byAccount != null && !byAccount.getId().equals(mid)) {
                byAccount.setOpenid(member.getOpenid());
                memberService.updateById(byAccount);
                memberService.removeById(member.getId());
                memberVO = dozerUtils.map(byAccount, MemberVO.class);
                return R.success(memberVO);
            }
        }
        if (phoneNoInfo.getPhoneNumber() != null && (member.getAccount() == null || member.getAccount().isEmpty())) {
            member.setAccount(phoneNoInfo.getPhoneNumber());
        }
//        if (member.getNickname() != null && member.getHeadimg() != null && member.getRongCloudToken() == null) {
//            if (!member.getNickname().isEmpty() && !member.getHeadimg().isEmpty()) {
//                System.out.println("第一次登陆");
//                String RongCloudToken = RongCloudUtils.getToken(member.getId(), member.getNickname(), member.getHeadimg());
//                member.setRongCloudToken(RongCloudToken);
//            }
//        }
        memberService.updateById(member);
        memberVO = dozerUtils.map(member, MemberVO.class);
//        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getOpenid(),
//                member.getNickname() == null ? null : member.getNickname(), member.getIsMain());
//        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
        return R.success(memberVO);
    }

    @Override
    @Transactional
    public R<AuthInfo> login(HttpServletRequest request, CommonAppLoginDTO appLoginDTO) {
        String env = request.getHeader("env");
        Member member = memberService.findByAccount(appLoginDTO.getAccount());
        if (member == null) {
            return R.fail("用户不存在，请先注册");
        }
        if (appLoginDTO.getAccount().length() != 11) {
            return R.fail("请输入正确的手机号");
        }
        if (!Objects.equals(member.getAccount(), appLoginDTO.getAccount())) {
            return R.fail("手机号不正确");
        }
        if (env != null && !env.equals("") && !env.equals("app") && member.getRoleType() != null) {
            //app用户，登录小小程序
            return R.fail("该账号已注册为商家/理疗车，不能用作小程序登录");
        }
        if (env != null && !env.equals("") && env.equals("app") && member.getRoleType() != null) {
            if (member.getRoleType().equals("3")) {
                return R.fail("该账号已注册为小程序用户");
            }
        }
        if (null == member) {
            return R.validFail("用户名或密码错误");
        }
        if (member.getStatus()) {
            return R.fail("您已被禁用");
        }


        if (StringUtils.isNotBlank(appLoginDTO.getPassWord())) {
            //密码校验
            boolean isMatch = passwordEncoder.matches(appLoginDTO.getPassWord(), member.getPassword());
            System.out.println(isMatch);
            if (!isMatch) {
                return R.fail("用户名或密码错误");
            }
        }

        // //缓存验证码
        //        String key = CacheKey
        //                .buildKey(CacheKey.LOGIN_USER, TemplateCodeType.CODE_LOGIN_USER.name(),
        //                        param.getPhone());
        //        cacheRepository.setExpire(key, code, CacheRepository.DEF_TIMEOUT_5M);

        if (StringUtils.isNotBlank(appLoginDTO.getCode())) {
            //短信验证码校验
            String key = CacheKey
                    .buildKey(CacheKey.LOGIN_USER, TemplateCodeType.CODE_LOGIN_USER.name(),
                            appLoginDTO.getAccount());
            String code = cacheRepository.get(key);
            if (StrUtil.isBlank(code) || !code.equals(appLoginDTO.getCode())) {
                return R.validFail("验证码错误");
            }
        }


        member.setLoginNum(member.getLoginNum() + 1).setLoginTime(LocalDateTime.now());
//        member.setLatitude(appLoginDTO.getLatitude());
//        member.setLongitude(appLoginDTO.getLongitude());
//        member.setOnLine(1);
//        if (!member.getNickname().isEmpty() && !member.getHeadimg().isEmpty()) {
//            String RongCloudToken = RongCloudUtils.getToken(member.getId(), member.getNickname(), member.getHeadimg());
//            member.setRongCloudToken(RongCloudToken);
//        }
        memberService.saveOrUpdate(member);
        String nickname = "";

        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getAccount(),
                member.getNickname());

        userInfo.setName(nickname);
        /*System.out.println(result.toString());
        Member members = memberService.findByOpenid(openid);
        System.out.println("-----------------" + member);
        Boolean a1 = false;
        if (null == members) {
//            member = Member.builder()
//                    .openid(openid)
//                    .loginTime(LocalDateTime.now())
//                    .unionid(result.getUnionid())
//                    .latitude(miniAppLoginDTO.getLatitude())
//                    .longitude(miniAppLoginDTO.getLongitude()).build();
            members = new Member();
            members.setOpenid(openid);
            members.setNickname("微信用户");
            members.setHeadimg("https://xsy-1308896693.cos.ap-shanghai.myqcloud.com/admin/2022/02/a0272351-b471-4d2b-ac6d-0120926fb269.png");
            members.setLoginTime(LocalDateTime.now());
        } else {
            members.setLoginNum(member.getLoginNum() + 1).setLoginTime(LocalDateTime.now());
        }
        memberService.saveOrUpdate(member);*/


        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, 86400L);
//        if(appLoginDTO.getWxCode()!=null){
//            WxMaJscode2SessionResult result = loginByCode(appLoginDTO.getWxCode());
//            if (null == result) {
//                return R.fail("微信登录失败");
//            }
//            String sessionKey = result.getSessionKey();
//            log.info("登录获取sessionKey:{}", sessionKey);
//            String openid = result.getOpenid();
//            authInfo.setOpenId(openid);
//            member.setOpenid(openid);
//            memberService.saveOrUpdate(member);
//        }
        authInfo.setUserType(member.getUserType());
        authInfo.setRoleType(member.getRoleType());
        if ((member.getRoleType() == null
                || (member.getRoleType() != 0 && member.getRoleType() != 1))
                && "app".equals(env)
        ) {
            /*if (member.getLoginNum()==1 && "app".equals(env)){*/

            authInfo.setIsRoleSet(true);
        } else {
            authInfo.setIsRoleSet(false);
        }

        //authInfo.setRoleType(member.getRoleType());
        //保留 做单账号登录使用
//        channel.set(CacheKey.TOKEN_USER_ID, authInfo.getToken(),"");
//        CacheObject tokenCache = channel.get(CacheKey.TOKEN_USER_ID, authInfo.getToken());
//        System.out.println(tokenCache.toString());
        //发布登录事件
        publisher.publishEvent(
                LoginEvent.builder().
                        mid(member.getId()).build());


        System.out.println("登录成功");
        return R.success(authInfo);
    }


    @Override
    @Transactional
    public R register(RegDTO regDTO) throws Exception {
        //注册
        Member member = memberService.findByAccount(regDTO.getAccount());
        if (null != member) {
            return R.fail("账号已存在");
        }
        if (regDTO.getAccount().length() != 11) {
            return R.fail("请输入正确的手机号");
        }
        if (!ValidatorUtil.checkPhone(regDTO.getAccount())) {
            return R.fail("请输入正确格式的手机号");
        }
        BigDecimal bigDecimal = new BigDecimal(0);
        Random random = new Random();
        member = new Member().setPhone(regDTO.getAccount())
                .setAccount(regDTO.getAccount())
                .setNickname(regDTO.getAccount())
                .setPassword(passwordEncoder.encode(regDTO.getPassWord()))
                .setHeadimg("https://xsy-1308896693.cos.ap-shanghai.myqcloud.com/admin/2022/02/a0272351-b471-4d2b-ac6d-0120926fb269.png")
                .setCoupons(bigDecimal)
                .setBalance(bigDecimal)
                .setReferPhone(regDTO.getReferPhone())
                .setTichneg(bigDecimal)
        /*.setRoleType(regDTO.getRoleType())*/;
        memberService.save(member);

//        if (member.getRongCloudToken() == null || member.getRongCloudToken() == "") {
//            String RongCloudToken = RongCloudUtils.getToken(member.getId(), member.getNickname(), member.getHeadimg());
//            member.setRongCloudToken(RongCloudToken);
//            memberService.updateById(member);
//        }
        /**
         * 判断有没有推荐人,有推荐人的话，保存推荐历史
         * 得到分享者的电话
         * 20211115
         * 推薦人得到小红心
         * 1、看是否开启这个功能
         */

        return R.success();
    }

    @Override
    public R updateByAccount(UpdateAppDTO updateAppDTO) {
        Member one = memberService.getOne(new QueryWrap<Member>().lambda().eq(Member::getAccount, updateAppDTO.getAccount()));


        if (StringUtils.isNotBlank(updateAppDTO.getOldPassword())) {
            //密码校验
            boolean isMatch = passwordEncoder.matches(updateAppDTO.getOldPassword(), one.getPassword());
            if (!isMatch) {
                return R.fail("用户名或密码错误");
            }
        }
        Member member = new Member();
        member.setAccount(updateAppDTO.getAccount());
        member.setPassword(passwordEncoder.encode(updateAppDTO.getNewPassword()));
        if (selectByAccount(updateAppDTO.getAccount(), updateAppDTO.getNewPassword())) {
            memberService.getBaseMapper().update(member, new QueryWrap<Member>().lambda().eq(Member::getAccount, member.getAccount()));
            passwordHis(member.getAccount(), member.getPassword());
            return R.success();
        } else {
            return R.fail("不能与近两次修改的密码相同");
        }
    }

    @Override
    public R update(CommonAppLoginDTO commonAppLoginDTO) {
        Member member = new Member();
        member.setPassword(passwordEncoder.encode(commonAppLoginDTO.getPassWord()));
        memberService.getBaseMapper().update(member, new QueryWrap<Member>().lambda().eq(Member::getAccount, commonAppLoginDTO.getAccount()));

//        member.setAccount(commonAppLoginDTO.getAccount());
//        member.setPassword(passwordEncoder.encode(commonAppLoginDTO.getPassWord()));
//        if (selectByAccount(commonAppLoginDTO.getAccount(), commonAppLoginDTO.getPassWord())) {
//
//            passwordHis(member.getAccount(), member.getPassword());
//            return R.success();
//        } else {
//            return R.fail("不能与近两次修改的密码相同");
//        }
        return R.success();
    }

    /**
     * 微信登录app
     *
     * @param miniAppLoginDTO
     * @return
     */
    @Override
    @Transactional
    public R<AuthInfo> loginAppByWxMa(MiniAppLoginDTO miniAppLoginDTO) throws Exception {
        Member tokenOpenId = getTokenOpenId(miniAppLoginDTO.getCode());

//        if (tokenOpenId.getUnionid() == null) {
//            return R.fail("系统错误,请联系客服");
//        }
        /**
         * 通过unionid查看是否已经登录过了
         */
//        Member member = memberService.findByUnionid(tokenOpenId.getUnionid());
//        if (member == null) {
//            member = new Member();
//            BeanUtils.copyProperties(tokenOpenId, member);
//            memberService.save(member);
//        }
//
//        member.setLoginTime(LocalDateTime.now()).setLoginNum(member.getLoginNum() == null ? 0 : member.getLoginNum() + 1);
////        if (!member.getNickname().isEmpty() && !member.getHeadimg().isEmpty()) {
////            System.out.println("第一次登陆");
////            String RongCloudToken = RongCloudUtils.getToken(member.getId(), member.getNickname(), member.getHeadimg());
////            member.setRongCloudToken(RongCloudToken);
////        }
//        memberService.updateById(member);
//        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getAccount(),
//                member.getNickname());
//
//
//
//        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
//        /**
//         *
//         */
//        XsyMemberBase data1 = xsyMemberBaseService.selectMemberBase(member.getId()).getData();
//        if (data1.getId() == null) {
//            XsyMemberBaseSaveDTO data = new XsyMemberBaseSaveDTO();
//            data.setNickname(member.getNickname());
//            data.setMid(member.getId());
//            data.setSex(member.getSex());
//            data.setSexTime(LocalDateTime.now());
//            data.setLiveProvince(member.getRegisterProvince());
//            data.setLiveProvinceCode(member.getProvinceCode());
//            data.setLiveCity(member.getRegisterCity());
//            data.setLiveCityCode(member.getCityCode());
//            data.setLiveArea(member.getRegisterArea());
//            data.setLiveAreaCode(member.getAreaCode());
//            data.setBirthday(member.getBirthday());
//            data.setMarryStatus(null);
//            data.setProfession(null);
//            data.setSalaryMax(null);
//            data.setSalaryMin(null);
//            data.setVehicleMin(null);
//            data.setVehicleMax(null);
//            xsyMemberBaseService.addMemberBase(data);
//        }
//        return R.success(authInfo);
        return null;
    }

    /**
     * 微信绑定电话
     *
     * @param regDTO
     * @return
     */
    @Override
    public R<AuthInfo> bindPhoneByCode(MiniAppPhoneDTO regDTO) {
        if (null != memberService.findByAccount(regDTO.getAccount())) {
            return R.validFail("手机号码已注册");
        }
        Member result = memberService.findById(regDTO.getMid());
        result.setPhone(regDTO.getAccount());
        result.setAccount(regDTO.getAccount());
        memberService.updateById(result);
        JwtUserInfo userInfo = new JwtUserInfo(result.getId(), result.getAccount(),
                result.getNickname());
        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
        return R.success(authInfo);
    }

    @Override
    public R logOffAccount(Long mid) {
        Member result = memberService.findById(mid);
        result.setAccount(MemberConstants.LOG_Off + result.getAccount());
        result.setOpenid(MemberConstants.LOG_Off + result.getOpenid());
        memberService.updateById(result);
        return R.success();
    }

    @Override
    public R logOutAccount(Long mid) {
        Member result = memberService.findById(mid);
        memberService.updateById(result);
        return R.success();
    }

    @Override
    public R<AuthInfo> shopLogin(CommonAppLoginDTO appLoginDTO) {
        Member member = memberService.findByAccount(appLoginDTO.getAccount());
        if (null == member) {
            return R.validFail("用户名或密码错误");
        }
        if (member.getStatus()) {
            return R.fail("您已被禁用");
        }
        if (StringUtils.isNotBlank(appLoginDTO.getPassWord())) {
            //密码校验
            boolean isMatch = passwordEncoder.matches(appLoginDTO.getPassWord(), member.getPassword());
            if (!isMatch) {
                return R.fail("用户名或密码错误");
            }
        }
//        if (physicalStoreService.finbUserId(member.getId()) == null) {
//            return R.fail("您还没有实体店");
//        }

        memberService.saveOrUpdate(member);
        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getAccount(),
                member.getNickname());
        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
        //发布登录事件
        publisher.publishEvent(
                LoginEvent.builder().
                        mid(member.getId()).build());
        return R.success(authInfo);
    }

    @Override
    public R<AuthInfo> loginByAdmin(CommonAppLoginDTO appLoginDTO) {
        Member member = memberService.findByAccount(appLoginDTO.getAccount());

        if (null == member) {
            return R.validFail("用户名或密码错误");
        }
        if (member.getStatus()) {
            return R.fail("您已被禁用");
        }
        if (StringUtils.isNotBlank(appLoginDTO.getPassWord())) {
            //密码校验
            boolean isMatch = appLoginDTO.getPassWord().equals(member.getPassword());
            if (!isMatch) {
                return R.fail("用户名或密码错误");
            }
        }


        member.setLoginNum(member.getLoginNum() + 1).setLoginTime(LocalDateTime.now());

        memberService.saveOrUpdate(member);

        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getAccount(),
                member.getNickname());
        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
        //发布登录事件
        publisher.publishEvent(
                LoginEvent.builder().
                        mid(member.getId()).build());
        return R.success(authInfo);
    }

    @Override
    public R<AuthInfo> appBindPhoneByCode(MiniAppPhoneDTO regDTO) {
        Member member = memberService.findById(regDTO.getMid());
        if (member == null) {
            return R.fail("系统错误,请联系客服");
        }
        Member byAccount = memberService.findByAccount(regDTO.getAccount());
//        if (byAccount != null) {
//            if (byAccount.getUnionid() != null && !member.getUnionid().equals(byAccount.getUnionid())) {
//                return R.fail("手机号码已注册");
//            }
//            //合并账户
//            byAccount.setUnionid(member.getUnionid());
//            memberService.updateById(byAccount);
//            //删除旧账户
//            memberService.removeById(member.getId());
//            JwtUserInfo userInfo = new JwtUserInfo(byAccount.getId(), byAccount.getAccount(),
//                    byAccount.getNickname(), byAccount.getIsMain());
//            userInfo.setSex(byAccount.getSex());
//            AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
//            return R.success(authInfo);
//        }
        member.setAccount(regDTO.getAccount());
        member.setPhone(regDTO.getAccount());
        member.setPassword(passwordEncoder.encode(regDTO.getPassWord()));
        memberService.updateById(member);
        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getAccount(),
                member.getNickname());
        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, null);
        //发布登录事件
        publisher.publishEvent(
                LoginEvent.builder().
                        mid(member.getId()).build());
        return R.success(authInfo);
    }

    @Override
    public R<String> getOpenidByCode(MiniAppLoginDTO regDTO) throws IOException {
        String getTokenUrl = MessageFormat.format(WxAPIHttpUrl.GET_OPENID_URL.getApiUrl(), wxAppConfiguration.getAppid(), wxAppConfiguration.getSecret(), regDTO.getCode());
        /**
         *返回参数
         {
         "access_token": "ACCESS_TOKEN",
         "expires_in": 7200,
         "refresh_token": "REFRESH_TOKEN",
         "openid": "OPENID",
         "scope": "SCOPE",
         "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
         }
         */
        JSONObject jsonObject = AuthUtil.doGetJson(getTokenUrl);

        String openid = jsonObject.getString("openid");
        return R.success(openid);
    }


    @Override
    public R<AuthInfo> addRelationAccount(HttpServletRequest request, CommonAppLoginDTO appLoginDTO) {
        Long mainMid = BaseContextHandler.getUserId();
        Member realtionMember = memberService.findByAccount(appLoginDTO.getAccount());
        if (realtionMember == null) {
            return R.fail("账号不存在");
        }
        if (realtionMember.getId().equals(mainMid)) {
            return R.fail("账号相同不能添加");
        }
        /**
         * 先添加关联关系
         */
        ceresRelationAcoountService.addRelationAccount(mainMid, realtionMember.getId());
        return login(request, appLoginDTO);
    }

    @Override
    public R deleteRelationAccount(Long relationId) {
        Long mainMid = BaseContextHandler.getUserId();
        ceresRelationAcoountService.deleteRelationAccount(mainMid, relationId);
        return R.success();
    }

    @Override
    public R<IPage<RelationAccountSearchDTO>> searchRelationAccount(IPage page, Long mid) {
        return R.success(ceresRelationAcoountService.searchRelationAccount(page, mid));
    }

    @Override
    public R<AuthInfo> loginRelationAccount(Long relationId) {

        /**
         * 先判断是否是关联账户
         */
        Long mainMid = BaseContextHandler.getUserId();
        if (!ceresRelationAcoountService.ifRelationAccount(mainMid, relationId)) {
            return R.fail("两个账户不是关联账户");
        }


        Member member = memberService.findById(relationId);
        if (null == member) {
            return R.validFail("用户名或密码错误");
        }
        if (member.getStatus()) {
            return R.fail("您已被禁用");
        }
        member.setLoginNum(member.getLoginNum() + 1).setLoginTime(LocalDateTime.now());
//        if (!member.getNickname().isEmpty() && !member.getHeadimg().isEmpty()) {
//            String RongCloudToken = RongCloudUtils.getToken(member.getId(), member.getNickname(), member.getHeadimg());
//            member.setRongCloudToken(RongCloudToken);
//        }
        memberService.saveOrUpdate(member);
        String nickname = "";


        JwtUserInfo userInfo = new JwtUserInfo(member.getId(), member.getAccount(),
                member.getNickname());

        userInfo.setName(nickname);

        AuthInfo authInfo = tokenUtil.createAuthInfo(userInfo, 86400L);

        //保留 做单账号登录使用
//        channel.set(CacheKey.TOKEN_USER_ID, authInfo.getToken(),"");
//        CacheObject tokenCache = channel.get(CacheKey.TOKEN_USER_ID, authInfo.getToken());
//        System.out.println(tokenCache.toString());
        //发布登录事件
        publisher.publishEvent(
                LoginEvent.builder().
                        mid(member.getId()).build());


        System.out.println("登录成功");
        return R.success(authInfo);
    }

    @Override
    public R setRoleType(SetRoleTypeDTO setRoleTypeDTO) {
        Member member = memberService.findByAccount(setRoleTypeDTO.getAccount());
        if (null == member) {
            return R.validFail("用户名错误");
        }
        member.setRoleType(setRoleTypeDTO.getRoleType());
        memberService.saveOrUpdate(member);
        return R.success();
    }

    @Override
    public R appOneLoginSetRoleType(Integer roleType) {
        Long mid = getMid();
        Member member = new Member();
        member.setRoleType(roleType);
        member.setId(mid);
        boolean b = memberService.updateById(member);

        return b ? R.success(roleType) : R.fail("设置失败");
    }


    /**
     * 微信登录根据code获取微信accesstoken和openid
     * chenke
     * 20211108
     *
     * @param code
     * @throws IOException
     */

    private Member getTokenOpenId(String code) throws IOException {
        //通过第一步获得的code获取微信授权信息
        String getTokenUrl = MessageFormat.format(WxAPIHttpUrl.GET_OPENID_URL.getApiUrl(), wxAppConfiguration.getAppid(), wxAppConfiguration.getSecret(), code);
        /**
         *返回参数
         {
         "access_token": "ACCESS_TOKEN",
         "expires_in": 7200,
         "refresh_token": "REFRESH_TOKEN",
         "openid": "OPENID",
         "scope": "SCOPE",
         "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
         }
         */
        JSONObject jsonObject = AuthUtil.doGetJson(getTokenUrl);

        String openid = jsonObject.getString("openid");
        String token = jsonObject.getString("access_token");
        String unionid = jsonObject.getString("unionid");
        //通过access_token和openid获取用户信息
        String getUserInfourl = MessageFormat.format(WxAPIHttpUrl.GET_USERINFO_URL.getApiUrl(), token, openid);
        /**
         *
         */
        JSONObject userInfoObject = AuthUtil.doGetJson(getUserInfourl);
        String nickname = userInfoObject.getString("nickname");
        String headimgurl = userInfoObject.getString("headimgurl");
        Member member = new Member()
                .setNickname(nickname)
                .setHeadimg(headimgurl);
        return member;
    }

    /**
     * 判断与近两次修改的密码相同
     *
     * @param account  手机号
     * @param password 新的密码
     * @return
     */
    private Boolean selectByAccount(String account, String password) {
        List<MemberPasswordHis> list = memberPasswordHisService.selectByAccount(account);
        for (MemberPasswordHis memberPasswordHis : list) {
            if (passwordEncoder.matches(password, memberPasswordHis.getPassword())) {
                return false;
            }
        }
        return true;
    }

    /**
     * 储存手机号，密码
     *
     * @param account  手机号
     * @param password 密码
     */
    private void passwordHis(String account, String password) {
        MemberPasswordHis memberPasswordHis = new MemberPasswordHis();
        memberPasswordHis.setAccount(account);
        memberPasswordHis.setPassword(password);
        memberPasswordHisService.save(memberPasswordHis);
    }
}
